home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_09_02
/
9n02066a
< prev
next >
Wrap
Text File
|
1990-12-17
|
8KB
|
287 lines
/*
Find multiple copies of the same file on a single disk
drive. Compiled under Microsoft C 6.0 using:
cl /Fs /W4 /Ox /AC no_dup.c
Compiles without modifications undder TURBO C integrated
environment.
In both cases requires compact memory model libraries.
*/
#include "no_dup.h"
Flag first_call = True;
GlobalOpt globalopt = { False, False, 0, 0L };
int main( int argc, char **argv )
{
DirEntry *current_file, *next_file;
DirList *path, *root, *new_path;
char current_path[MAX_PATH], file_spec[MAX_FLEN];
PtrList *ptrbase, *ptrlist;
Flag duplicate = False;
for( ; argc > 1; argc-- )
{
if(argv[argc-1][1] == 'f' || argv[argc-1][1] == 'F')
globalopt.file = True;
else if( argv[argc-1][1] == 'd'
|| argv[argc-1][1] == 'D' )
globalopt.dir = True;
else
fprintf( stderr,
"Invalid command line switch: %s\n",
argv[argc-1] );
}
strcpy( file_spec, "*.*" );
current_file = NULL;
(void) getcwd( current_path, MAX_PATH );
fprintf( stderr, "%s\n", VERSION );
printf( "Processing %s\n", current_path );
path = make_path( current_path, "", NULL );
new_path = root = path;
if( (ptrbase = malloc( sizeof( PtrList ) * MAX_FILES ))
== NULL )
{
fprintf( stderr, "Insufficient near memory.\n" );
exit( EXIT_FAILURE );
}
ptrlist = ptrbase;
while( (path = get_path( root ) ) != NULL )
{
strcpy( current_path, path->pathname );
strcat( current_path, file_spec );
first_call = True;
while( (current_file = get_direntry(current_path))
!= NULL )
{
current_file->path = path->pathname;
if( current_file->attrib & FA_DIREC )
{
new_path = make_path( path->pathname,
current_file->name, new_path );
}
else
{
++globalopt.file_count;
globalopt.total_file_size
+= current_file->size;
if( globalopt.file_count == MAX_FILES )
{
fprintf( stderr,
"Too many files\n"
"Program is limited to %u files.\n",
MAX_FILES );
exit( EXIT_FAILURE );
}
*ptrlist = ( char * ) current_file;
++ptrlist;
}
}
path->dir_processed = True;
}
*ptrlist = NULL;
printf( "Processed %d files occupying %lu bytes.\n",
globalopt.file_count,
globalopt.total_file_size );
qsort( (void *) ptrbase,
(size_t) globalopt.file_count,
(size_t) sizeof( PtrList ), name_comp );
if( globalopt.file ) /* optionally list files */
{
printf( SEPARATOR );
printf( "Listing of all files below %s\n",root);
for( ptrlist = ptrbase; *ptrlist; ptrlist++ )
fprint_direntry( stdout,
(DirEntry *) *ptrlist );
}
printf( SEPARATOR );
printf( "Duplicate files below %s\n", root );
for( ptrlist = ptrbase, duplicate = False;
*ptrlist; ptrlist++ )
{
current_file = ( DirEntry * ) *ptrlist;
next_file = ( DirEntry * ) *(ptrlist+1);
if( !strcmp(current_file->name,next_file->name))
{
duplicate = True;
fprint_direntry( stdout, current_file );
}
else if( duplicate == True )
{
/* print the last file in a group */
/* otherwise we'll miss it */
current_file = ( DirEntry * ) *ptrlist;
fprint_direntry( stdout, current_file );
printf( SEPARATOR );
duplicate = False;
}
}
return EXIT_SUCCESS;
}
/*
get file info from DOS directory and allocate memory
*/
DirEntry *get_direntry( char *path )
{
static struct ffblk file_info;
DirEntry *new_entry;
if( first_call == True )
{
if( findfirst( path, &file_info, FA_DIREC ) )
return NULL;
first_call = False;
}
else
{
if( findnext( &file_info ) )
{
return NULL;
}
}
if( (new_entry = malloc(sizeof(DirEntry))) == NULL )
{
fprintf( stderr, "Insufficient far memory.\n" );
exit( EXIT_FAILURE );
}
strcpy( new_entry->name, file_info.ff_name );
new_entry->attrib = file_info.ff_attrib;
if( new_entry->attrib & FA_DIREC )
new_entry->dir_processed = False;
new_entry->time = file_info.ff_ftime;
new_entry->date = file_info.ff_fdate;
new_entry->size = file_info.ff_fsize;
return new_entry;
}
/*
build a directory path by appending subdir to basedir
*/
DirList *make_path( char *basedir, char *subdir,
DirList *prev )
{
DirList *new_dir;
if( (new_dir = malloc( sizeof( DirList ) ) ) == NULL )
{
fprintf( stderr, "Insufficient near memory.\n" );
exit( EXIT_FAILURE );
}
strcpy( new_dir->pathname, basedir );
strcat( new_dir->pathname, subdir );
if( *(new_dir->pathname + strlen(new_dir->pathname) - 1)
!= '\\' )
strcat( new_dir->pathname, "\\" );
if( strcmp( subdir, "." ) && strcmp( subdir, ".." ) )
{
/* only "real" directories meet the condition */
new_dir->dir_processed = False;
if( globalopt.dir )
printf( "Directory:%s\n", new_dir->pathname );
}
else
new_dir->dir_processed = True;
if( prev )
{
new_dir->prev = prev;
new_dir->next = NULL;
prev->next = new_dir;
}
else
{
new_dir->prev = NULL;
new_dir->next = NULL;
}
return new_dir;
}
/*
find an unprocessed directory
*/
DirList *get_path( DirList *root )
{
DirList *path;
path = root;
while( path->next && (path->dir_processed == True) )
{
path = path->next;
}
if( path->dir_processed == True)
return NULL;
else
return path;
}
/*
DirEntry comparison function
*/
int name_comp( const void *p1, const void *p2 )
{
PtrList *ptr1, *ptr2;
DirEntry *f1, *f2;
int status;
ptr1 = (PtrList *) p1;
ptr2 = (PtrList *) p2;
f1 = (DirEntry *) *ptr1;
f2 = (DirEntry *) *ptr2;
if( status = strcmp( f1->name, f2->name ) )
return( status );
else if( status = f1->date - f2->date )
return( status );
else if( status = f1->time - f2->time )
return( status );
else
return( strcmp( f1->path, f2->path ) );
}
/*
print file information to the ouptut stream
*/
void fprint_direntry( FILE *fout, DirEntry *current_file )
{
char date_buf[10], time_buf[10];
fprintf( fout, "%-14s %6ld %c%c %s %s %s\n",
current_file->name,
current_file->size,
(current_file->attrib & FA_RDONLY ) ? 'R' : '.',
(current_file->attrib & FA_ARCH ) ? 'A' : '.',
datestr( current_file->date, date_buf ),
timestr( current_file->time, time_buf ),
current_file->path );
}
/*
The following functions are copied from QC 2.0 online
help. These functions convert wr_time and wr_date into
strings.
*/
char *timestr( unsigned t, char *buf )
{
int h = (t >> 11) & 0x1f, m = (t >> 5) & 0x3f;
sprintf( buf, "%2.2d:%02.2d", h, m );